/** QC/TODO Pending  - chk cleanup
 * 02-Apr-2011 Created
 */
package com.munoor.dalai.server.api;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;

import com.munoor.dalai.server.model.Company;
import com.munoor.dalai.server.model.EMFService;
import com.munoor.dalai.server.model.Filter;
import com.munoor.dalai.server.model.Listing;
import com.munoor.dalai.server.model.ListingMetadata;
import com.munoor.dalai.server.model.ListingView;
import com.munoor.dalai.server.model.wrappers.WrappedEntityList;
import com.munoor.dalai.server.model.wrappers.WrappedListing;
import com.munoor.dalai.server.model.wrappers.WrappedListingList;
import com.munoor.dalai.server.model.wrappers.WrappedListingMetadata;
import com.munoor.dalai.server.model.wrappers.WrappedListingMetadataList;
import com.munoor.dalai.server.model.wrappers.WrappedListingView;
import com.munoor.dalai.server.model.wrappers.WrappedListingViewList;
import com.sun.jersey.api.NotFoundException;

/**
 * @author Osho Ilamah
 * @since version 1.0 (07 April 2011)
 */
@Path("users/{userId}/listings")
public class ListingsService {
	@Context
	UriInfo uriInfo;
	@Context
	Request request;

	@SuppressWarnings("unchecked")
	@GET
	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	public WrappedEntityList getListings(@QueryParam("type") @DefaultValue("0") int type, @QueryParam("userId") @DefaultValue("65") int userId,
			@QueryParam("scanned") @DefaultValue("1304226000") long scanned, @QueryParam("start") @DefaultValue("0") int start, @QueryParam("items") @DefaultValue("10") int items) {
		// type = preview | view | fetch
		// type = 0 | 1 | 2
		EntityManager em = EMFService.get().createEntityManager();

		Filter activeFilter = null;
		//boolean hasFilter = false;
		int filterOption = 0;
		try {
			List<Filter> activeFilterObjects = em.createNamedQuery("Filters.findActiveByUserId").setParameter("userId", userId).setMaxResults(5).getResultList();
			if (!activeFilterObjects.isEmpty()){
				activeFilter = (Filter) activeFilterObjects.get(0);
				if (activeFilter.getCategoryId() < 1000){
					filterOption = 4;  //sets bit 3 =8
				}
				if (activeFilter.getLevelId()> 0){
					filterOption = filterOption | 2;  //sets bit 2 >=2
				}
				if (activeFilter.getLocationId().length() > 2){
					filterOption = filterOption | 1;  //sets bit 1 >=1
				}				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			Query resultsQuery = null;
			Query resultsCountQuery = null;
			switch (filterOption){
			case 7:
				resultsQuery = em.createNamedQuery("Listing.findByCategoryLevelLocation").setParameter("categoryId", activeFilter.getCategoryId()).setParameter("levelId", activeFilter.getLevelId()).setParameter("locationId", activeFilter.getLocationId());
				resultsCountQuery = em.createNamedQuery("Listing.countByCategoryLevelLocation").setParameter("categoryId", activeFilter.getCategoryId()).setParameter("levelId", activeFilter.getLevelId()).setParameter("locationId", activeFilter.getLocationId());
				break;
			case 6:
				resultsQuery = em.createNamedQuery("Listing.findByCategoryLevel").setParameter("categoryId", activeFilter.getCategoryId()).setParameter("levelId", activeFilter.getLevelId());
				resultsCountQuery = em.createNamedQuery("Listing.countByCategoryLevel").setParameter("categoryId", activeFilter.getCategoryId()).setParameter("levelId", activeFilter.getLevelId());
				break;
			case 5:
				resultsQuery = em.createNamedQuery("Listing.findByCategoryLocation").setParameter("categoryId", activeFilter.getCategoryId()).setParameter("locationId", activeFilter.getLocationId());
				resultsCountQuery = em.createNamedQuery("Listing.countByCategoryLocation").setParameter("categoryId", activeFilter.getCategoryId()).setParameter("locationId", activeFilter.getLocationId());
				break;
			case 4:
				resultsQuery = em.createNamedQuery("Listing.findByCategory").setParameter("categoryId", activeFilter.getCategoryId());
				resultsCountQuery = em.createNamedQuery("Listing.countByCategory").setParameter("categoryId", activeFilter.getCategoryId());
				break;
			case 3:
				resultsQuery = em.createNamedQuery("Listing.findByLevelLocation").setParameter("levelId", activeFilter.getLevelId()).setParameter("locationId", activeFilter.getLocationId());
				resultsCountQuery = em.createNamedQuery("Listing.countByLevelLocation").setParameter("levelId", activeFilter.getLevelId()).setParameter("locationId", activeFilter.getLocationId());
				break;
			case 2:
				resultsQuery = em.createNamedQuery("Listing.findByLevel").setParameter("levelId", activeFilter.getLevelId());
				resultsCountQuery = em.createNamedQuery("Listing.countByLevel").setParameter("levelId", activeFilter.getLevelId());
				break;
			case 1:
				resultsQuery = em.createNamedQuery("Listing.findByLocation").setParameter("locationId", activeFilter.getLocationId());
				resultsCountQuery = em.createNamedQuery("Listing.countByLocation").setParameter("locationId", activeFilter.getLocationId());
				break;
			default:
				resultsQuery = em.createNamedQuery("Listing.findAll");
				resultsCountQuery = em.createNamedQuery("Listing.countAll");
			}
			
    		System.out.println("  Parameterize Start");

			// parameterize and execute the query
			List<Listing> listingObjects = resultsQuery.setParameter("lastScan", scanned).setFirstResult(start).setMaxResults(items).getResultList();
			int existingCount = ((Integer) resultsCountQuery.setParameter("lastScan", scanned).getSingleResult()).intValue();
			int nextStart = existingCount > (start + items) ? (start + items) : 0;
			int prevStart = (start - items) > 0 ? (start - items) : 0;
			String next = "";
			if (nextStart > 0) {
				next = "start=" + nextStart + "&items=" + items;
			}

			WrappedEntityList wrappedListingsList = null;
			System.out.println("  Parameterize Finish");
			switch (type) {
			case 0:
				ListingMetadata metadata = null;
				List<WrappedListingMetadata> listingMetadataWrappers = new ArrayList<WrappedListingMetadata>();
				for (Listing l : listingObjects) {
					metadata = new ListingMetadata();
					metadata.setTitle(l.getTitle());
					metadata.setCompany(((Company) em.createNamedQuery("Companies.findByCompanyId").setParameter("companyId", l.getCompanyId()).getSingleResult()).getCompanyName());
					metadata.setListingId(l.getListingId());
					listingMetadataWrappers.add(new WrappedListingMetadata(metadata));
				}
				wrappedListingsList = new WrappedListingMetadataList(listingMetadataWrappers, next, "start=" + prevStart + "&items=" + items, start, listingObjects.size(),
						existingCount);
				break;
			case 1:
				ListingView listing = null;
				List<WrappedListingView> listingViewWrappers = new ArrayList<WrappedListingView>();
				for (Listing l : listingObjects) {
					listing = new ListingView(l);
					listing.setCompany(((Company) em.createNamedQuery("Companies.findByCompanyId").setParameter("companyId", l.getCompanyId()).getSingleResult()).getCompanyName());
					listingViewWrappers.add(new WrappedListingView(listing));
				}
				wrappedListingsList = new WrappedListingViewList(listingViewWrappers, next, "start=" + prevStart + "&items=" + items, start, listingObjects.size(), existingCount);
				break;
			case 2:
				List<WrappedListing> listingWrappers = new ArrayList<WrappedListing>();
				for (Listing l : listingObjects) {
					listingWrappers.add(new WrappedListing(l));
				}
				wrappedListingsList = new WrappedListingList(listingWrappers, next, "start=" + prevStart + "&items=" + items, start, listingObjects.size(), existingCount);
			}
			System.out.println("  Return");
			return wrappedListingsList;
		} catch (Exception e) {
			throw new NotFoundException("Not Found");
		} finally {
			em.close();
		}
	}

	// SUB-RESOURCE CALLS
	// methods, etc to be handled by sub-resource
	@Path("{listingId}")
	// = users/{userId}/listings/{listingId}
	public ListingResource getListing(@PathParam("listingId") Long listingId) {
		return new ListingResource(uriInfo, request, listingId);
	}
}
